package com.qs.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qs.constant.RedisConstant;
import com.qs.constant.StatusConstant;
import com.qs.exception.ServiceException;
import com.qs.mapper.AreaMapper;
import com.qs.mapper.UserMapper;
import com.qs.pojo.dto.AddressDto;
import com.qs.pojo.entity.Address;
import com.qs.mapper.AddressMapper;
import com.qs.pojo.entity.Area;
import com.qs.pojo.entity.User;
import com.qs.response.ResponseEnum;
import com.qs.service.IAddressService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户地址表 服务实现类
 * </p>
 *
 * @author author
 * @since 2023-11-21
 */
@Service
@RequiredArgsConstructor
public class AddressServiceImpl extends ServiceImpl<AddressMapper, Address> implements IAddressService {

    private final UserMapper userMapper;

    private final RedisTemplate redisTemplate;

    private final AreaMapper areaMapper;

    @Override
    public void saveAddress(Address address) {
        //查询验证码是否过期
        String code = (String) redisTemplate.opsForValue().get(RedisConstant.MESSAGE_CODE + address.getPhone());
        if(StringUtils.isEmpty(code)){
            throw new ServiceException(ResponseEnum.CODE_TIMEOUT);
        }
        //对比验证码是否正确
        if(!address.getCode().equalsIgnoreCase(code)){
            throw new ServiceException(ResponseEnum.CODE_ERROR);
        }
        //查询是否已经有默认地址，如果有则抛异常
        if(address.getStatus().intValue() == StatusConstant.STATUS_ADDRESS){
            QueryWrapper<Address> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id",address.getUserId());
            List<Address> addressList = baseMapper.selectList(wrapper);
            List<Address> list = addressList.stream().filter(item -> item.getStatus().intValue() == StatusConstant.STATUS_ADDRESS).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(list)){
                throw new ServiceException(ResponseEnum.ADDRESS_DEFAULT_EXITS);
            }
        }
        //每个用户只能有5个收获地址
        QueryWrapper<Address> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",address.getUserId());
        List<Address> addressList = baseMapper.selectList(wrapper);
        if(!CollectionUtils.isEmpty(addressList)){
            if(addressList.size() >= 5){
                throw new ServiceException(ResponseEnum.ADDRESS_IS_FULL);
            }
        }
        baseMapper.insert(address);
    }

    @Override
    public List<AddressDto> getList(Integer userId) {
        if(null != userId){
            QueryWrapper<Address> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", userId);
            wrapper.orderByDesc("status", StatusConstant.STATUS_ADDRESS.toString());
            wrapper.orderByDesc("update_time");
            List<Address> addressList = baseMapper.selectList(wrapper);
            User user = userMapper.selectById(userId);
            if(!CollectionUtils.isEmpty(addressList)){
                List<AddressDto> list = new ArrayList<>();
                addressList.stream().forEach(item -> {
                    AddressDto addressDto = new AddressDto();
                    BeanUtils.copyProperties(item,addressDto);
                    addressDto.setAvatar(user.getAvatar());
                    addressDto.setRegionDetails(item.getRegion() + item.getDetail());
                    list.add(addressDto);
                });
                return list;
            }
        }
        return null;
    }

    @Override
    public Address echoById(Integer id) {
        if(null != id){
            Address address = baseMapper.selectById(id);
            if(address.getStatus().intValue() == StatusConstant.STATUS_ADDRESS){
                address.setChecked(true);
            }
            return address;
        }
        return null;
    }

    @Override
    public void updateAddress(Address address) {
        //查询是否已经有默认地址，如果有则抛异常
        if(address.getStatus().intValue() == StatusConstant.STATUS_ADDRESS){
            QueryWrapper<Address> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id",address.getUserId());
            List<Address> addressList = baseMapper.selectList(wrapper);
            List<Address> list = addressList.stream().filter(item -> item.getStatus().intValue() == StatusConstant.STATUS_ADDRESS).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(list)){
                Address finalAddress = list.get(0);
                if(finalAddress.getId().intValue() != address.getId()){
                    throw new ServiceException(ResponseEnum.ADDRESS_DEFAULT_EXITS);
                }
            }
        }
        baseMapper.updateById(address);

    }

    @Override
    public AddressDto getAddressById(Integer addressId) {
        Address address = baseMapper.selectById(addressId);
        AddressDto addressDto = new AddressDto();
        BeanUtils.copyProperties(address,addressDto);
        addressDto.setRegionDetails(address.getRegion() + address.getDetail());
        return addressDto;
    }

    @Override
    public List<Tree<String>> getAllAreaData() {
        List<Tree<String>> treeList = (List<Tree<String>>) redisTemplate.opsForValue().get(RedisConstant.AREA);
        if(!CollectionUtils.isEmpty(treeList)){
            return treeList;
        }
        List<Area> areaList = areaMapper.selectList(null);
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 最大递归深度
        treeNodeConfig.setDeep(4);
        List<Tree<String>> treeNodes = TreeUtil.build(areaList, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId().toString());
                    tree.setParentId(treeNode.getParentId().toString());
                    // 扩展属性 ...
                    tree.putExtra("value", treeNode.getName());
                    tree.putExtra("label", treeNode.getName());
                });
        //进行redis缓存
        redisTemplate.opsForValue().set(RedisConstant.AREA,treeNodes);
        return treeNodes;
    }
}
